package cntv.player.media.player;

import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.Surface;
import android.view.SurfaceHolder;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Map;

import io.vov.vitamio.MediaFormat;
import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.MediaPlayer.TrackInfo;
import io.vov.vitamio.Metadata;

public class VitamioMediaPlayer extends SimpleMediaPlayer {

	private MediaPlayer mInternalMediaPlayer;
	private VitamioMediaPlayerListenerHolder mInternalListenerAdapter;
	private String mDataSource;
	private OnTimedTextListener mOnTimedTextListener;

	private Object mInitLock = new Object();
	private boolean mIsReleased;
	private boolean mKeepInBackground;

	private MediaInfo sMediaInfo;

    public VitamioMediaPlayer(Context ctx) {
        synchronized (mInitLock) {
            mInternalMediaPlayer = new MediaPlayer(ctx);
        }
//        mInternalMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mInternalListenerAdapter = new VitamioMediaPlayerListenerHolder(this);
        attachInternalListeners();
    }

    @Override
    public void setDisplay(SurfaceHolder sh) {
    	mInternalMediaPlayer.setDisplay(sh);
        /*synchronized (mInitLock) {
            if (!mIsReleased) {
                mInternalMediaPlayer.setDisplay(sh);
                if (sh != null)
                    sh.addCallback(mSurfaceCallback);
            }
        }*/
    }

/*    private SurfaceHolder.Callback mSurfaceCallback = new Callback() {
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
        }

        public void surfaceCreated(SurfaceHolder holder) {
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            if (mInternalMediaPlayer != null) {
                if (!mKeepInBackground) {
                    mInternalMediaPlayer.release();
                }
            }
        }
    };*/

    @Override
    public void setSurface(Surface surface) {
        mInternalMediaPlayer.setSurface(surface);
    }

    @Override
    public void setDataSource(String path) throws IOException,
            IllegalArgumentException, SecurityException, IllegalStateException {
        mDataSource = path;

        Uri uri = Uri.parse(path);
        String scheme = uri.getScheme();
        if (!TextUtils.isEmpty(scheme) && scheme.equalsIgnoreCase("file")) {
            mInternalMediaPlayer.setDataSource(uri.getPath());
        } else {
            mInternalMediaPlayer.setDataSource(path);
        }
    }
    
    public void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
    	mDataSource = uri.getPath();
        mInternalMediaPlayer.setDataSource(context, uri);
    }
    
    public void setDataSource(Context context, Uri uri, Map<String, String> headers) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
    	mDataSource = uri.getPath();
        mInternalMediaPlayer.setDataSource(context, uri, headers);
    }
    public void setDataSource(String path, Map<String, String> headers) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException{
    	mDataSource = path;
        mInternalMediaPlayer.setDataSource(path, headers);
    }
	public void setDataSource(String path, String[] keys, String[] values) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
		mDataSource = path;
        mInternalMediaPlayer.setDataSource(path, keys, values);
	}

    @Override
    public String getDataSource() {
        return mDataSource;
    }

    @Override
    public void prepareAsync() throws IllegalStateException {
        mInternalMediaPlayer.prepareAsync();
    }

    @Override
    public void start() throws IllegalStateException {
        mInternalMediaPlayer.start();
    }

    @Override
    public void stop() throws IllegalStateException {
        mInternalMediaPlayer.stop();
    }

    @Override
    public void pause() throws IllegalStateException {
        mInternalMediaPlayer.pause();
    }

    @Override
    public void setScreenOnWhilePlaying(boolean screenOn) {
        mInternalMediaPlayer.setScreenOnWhilePlaying(screenOn);
    }

    @Override
    public int getVideoWidth() {
        return mInternalMediaPlayer.getVideoWidth();
    }

    @Override
    public int getVideoHeight() {
        return mInternalMediaPlayer.getVideoHeight();
    }
    
    @Override
    public float getVideoAspectRatio() {
    	// TODO Auto-generated method stub
    	return mInternalMediaPlayer.getVideoAspectRatio();
    }

    @Override
    public int getVideoSarNum() {
        return 1;
    }

    @Override
    public int getVideoSarDen() {
        return 1;
    }

    @Override
    public boolean isPlaying() {
        try {
            return mInternalMediaPlayer.isPlaying();
        } catch (IllegalStateException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void seekTo(long msec) throws IllegalStateException {
        mInternalMediaPlayer.seekTo((int) msec);
    }

    @Override
    public long getCurrentPosition() {
        try {
            return mInternalMediaPlayer.getCurrentPosition();
        } catch (IllegalStateException e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public long getDuration() {
        try {
            return mInternalMediaPlayer.getDuration();
        } catch (IllegalStateException e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public void release() {
        mIsReleased = true;
        mInternalMediaPlayer.release();

        resetListeners();
        resetInternalListeners();
        attachInternalListeners();
    }

    @Override
    public void reset() {
        mInternalMediaPlayer.reset();

        resetListeners();
        attachInternalListeners();
    }

    @Override
    public MediaInfo getMediaInfo() {
        if (sMediaInfo == null) {
            MediaInfo module = new MediaInfo();

            module.mVideoDecoder = "android";
            module.mVideoDecoderImpl = "HW";

            module.mAudioDecoder = "android";
            module.mAudioDecoderImpl = "HW";

            sMediaInfo = module;
        }

        return sMediaInfo;
    }

	/*--------------------
	 * misc
	 */
	@Override
	public void setWakeMode(Context context, int mode) {
		mInternalMediaPlayer.setWakeMode(context, mode);
	}

	@Override
	public void setAudioStreamType(int streamtype) {
		// mInternalMediaPlayer.setAudioStreamType(streamtype);
	}

	@Override
	public void setKeepInBackground(boolean keepInBackground) {
		mKeepInBackground = keepInBackground;
	}

	public void setVolume(float leftVolume, float rightVolume) {
		mInternalMediaPlayer.setVolume(leftVolume, rightVolume);
	}

	public void setVideoChroma(int chroma) {
		mInternalMediaPlayer.setVideoChroma(chroma);
	}

	public void setVideoQuality(int quality) {
		mInternalMediaPlayer.setVideoQuality(quality);
	}

	public int getAudioTrack() {
		return mInternalMediaPlayer.getAudioTrack();
	}

	public void selectTrack(int index) {
		mInternalMediaPlayer.selectTrack(index);
	}

	public void setTimedTextShown(boolean shown) {
		mInternalMediaPlayer.setTimedTextShown(shown);
	}

	public void setTimedTextEncoding(String encoding) {
		mInternalMediaPlayer.setTimedTextEncoding(encoding);
	}

	public int getTimedTextTrack() {
		return mInternalMediaPlayer.getTimedTextTrack();
	}

	public void addTimedTextSource(String subPath) {
		mInternalMediaPlayer.addTimedTextSource(subPath);
	}

	public String getTimedTextPath() {
		return mInternalMediaPlayer.getTimedTextPath();
	}

	public int getTimedTextLocation() {
		return mInternalMediaPlayer.getTimedTextLocation();
	}

	public void setBufferSize(long bufSize) {
		mInternalMediaPlayer.setBufferSize(bufSize);
	}

	public boolean isBuffering() {
		return mInternalMediaPlayer.isBuffering();
	}

	public String getMetaEncoding() {
		return mInternalMediaPlayer.getMetaEncoding();
	}

	public Metadata getMetadata() {
		return mInternalMediaPlayer.getMetadata();
	}

	public void setMetaEncoding(String encoding) {
		mInternalMediaPlayer.setMetaEncoding(encoding);
	}

	public TrackInfo[] getTrackInfo(String encoding) {
		return mInternalMediaPlayer.getTrackInfo();
	}

	public SparseArray<MediaFormat> findTrackFromTrackInfo(int mediaTrackType, TrackInfo[] trackInfo) {
		return mInternalMediaPlayer.findTrackFromTrackInfo(mediaTrackType, trackInfo);
	}
	
	private void resetInternalListeners(){
		mInternalListenerAdapter = null;
	}
	
    /*--------------------
     * Listeners adapter
     */
    private final void attachInternalListeners() {
        mInternalMediaPlayer.setOnPreparedListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnBufferingUpdateListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnCompletionListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnSeekCompleteListener(mInternalListenerAdapter);
        mInternalMediaPlayer .setOnVideoSizeChangedListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnErrorListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnInfoListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnTimedTextListener(mInternalListenerAdapter);
    }
    
    public void setOnTimedTextListener(OnTimedTextListener listener) {
    	mOnTimedTextListener = listener;
    }

	private class VitamioMediaPlayerListenerHolder implements
			MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener,
			MediaPlayer.OnBufferingUpdateListener,
			MediaPlayer.OnSeekCompleteListener,
			MediaPlayer.OnVideoSizeChangedListener,
			MediaPlayer.OnErrorListener, 
			MediaPlayer.OnInfoListener,
			MediaPlayer.OnTimedTextListener{
		public WeakReference<VitamioMediaPlayer> mWeakMediaPlayer;

		public VitamioMediaPlayerListenerHolder(VitamioMediaPlayer mp) {
			mWeakMediaPlayer = new WeakReference<VitamioMediaPlayer>(mp);
		}

		@Override
		public boolean onInfo(MediaPlayer mp, int what, int extra) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return false;

			return notifyOnInfo(what, extra);
		}

		@Override
		public boolean onError(MediaPlayer mp, int what, int extra) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return false;

			return notifyOnError(what, extra);
		}

		@Override
		public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;

			notifyOnVideoSizeChanged(width, height, 1, 1);
		}

		@Override
		public void onSeekComplete(MediaPlayer mp) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;

			notifyOnSeekComplete();
		}

		@Override
		public void onBufferingUpdate(MediaPlayer mp, int percent) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;

			notifyOnBufferingUpdate(percent);
		}

		@Override
		public void onCompletion(MediaPlayer mp) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;

			notifyOnCompletion();
		}

		@Override
		public void onPrepared(MediaPlayer mp) {
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;

			notifyOnPrepared();
		}

		@Override
		public void onTimedText(String text) {
			// TODO Auto-generated method stub
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;
			
			if(mOnTimedTextListener != null){
				mOnTimedTextListener.onTimedText(text);
			}
		}

		@Override
		public void onTimedTextUpdate(byte[] pixels, int width, int height) {
			// TODO Auto-generated method stub
			VitamioMediaPlayer self = mWeakMediaPlayer.get();
			if (self == null)
				return;
			
			if(mOnTimedTextListener != null){
				mOnTimedTextListener.onTimedTextUpdate(pixels, width, height);
			}
		}
	}

}
